import { MapConfigs } from "./MapConfigs";
import { Terrain } from "./Terrain"; // 确保 Terrain 类路径正确
import { TerrainList } from "./TerrainList"; // 确保 TerrainList 类路径正确
import { TerrainConfig, TerrainConfigItem, TerrainConfigManager, TerrainType } from "./utils/TerrainConfigManager"; // 确保配置管理器路径正确
import { WoundedScript } from "./WoundedScript";

const { regClass, property } = Laya;

@regClass()
export class MainScript extends Laya.Script {


    // --- UI组件 ---
    @property(String)
    public mapId: string = null; // 地图背景图，用于获取尺寸
    // --- UI组件 ---
    @property(Laya.Image)
    public Image_map: Laya.Image = null; // 地图背景图，用于获取尺寸

    @property(Laya.Box)
    public box_map: Laya.Box = null; // 放置可拖动地形的容器

    @property(Laya.Box)
    public box_game: Laya.Box = null; // 游戏主容器，背景和格子放这里

    @property(Laya.Box)
    public box_list: Laya.Box = null; // 放置地形列表UI的容器

    @property(Laya.Button)
    public box_export: Laya.Button = null; // 导出按钮

    @property(Laya.Button)
    public box_load: Laya.Button = null; // 加载/导入按钮

    @property(Laya.Button)
    public box_open: Laya.Button = null; // 加载/导入按钮



    // --- 建筑/地形相关 ---
    private terrainList: TerrainList;        // 地形列表UI实例
    private selectedTerrain: Terrain = null; // 当前选中的地形对象
    private draggingTerrain: Terrain = null; // 当前正在拖动的地形对象

    // --- 拖拽相关 ---
    private offsetX: number = 0; // 鼠标按下时相对于地形中心点的X偏移
    private offsetY: number = 0; // 鼠标按下时相对于地形中心点的Y偏移

    // --- 地图格子 ---
    // 存储从 JSON 加载的详细格子信息 (包含 x, y, row, col, type)
    private gridData: Array<Array<{ id: number, x: number, y: number, row: number, column: number, type: number }>> = [];
    // 地图格子状态二维数组 (用于快速查询占用状态: 0=空, -1=边界, 其他=地形type/id)
    private mapGrid: Array<Array<{ id: number, x: number, y: number, row: number, column: number, type: number }>> = [];
    // 用于绘制格子的容器 Sprite
    private gridContainer: Laya.Sprite = null;
    // --- 格子配置 ---
    private readonly gridWidth: number = 50; // 格子宽度 (菱形宽度)
    private readonly gridVisualHeight: number = 25; // 菱形实际视觉高度
    private readonly gridRowSpacing: number = this.gridVisualHeight / 2; // 行间距 = 12.5


    map_width_pixels = 2048
    map_height_pixels = 2304
    /**
     * 组件被激活后执行，此时所有节点和组件均已创建完毕，此方法只执行一次
     */
    async onAwake() {
        console.log("MainScript onAwake started.");
        await TerrainConfigManager.getInstance().loadConfig(this.mapId)
        let mapConfigs = MapConfigs.getMapConfig(this.mapId)
        this.map_width_pixels = mapConfigs.size.width
        this.map_height_pixels = mapConfigs.size.height

        // 1. 创建用于绘制格子的容器，并添加到游戏层底部
        this.gridContainer = new Laya.Sprite();
        this.gridContainer.name = "GridContainer"; // 方便调试时查找
        if (this.box_game) {
            this.box_game.addChild(this.gridContainer);
            // 确保格子绘制在最底层，其他游戏元素（如地图背景Image_map如果也在box_game里）应该在它之上
            this.box_game.setChildIndex(this.gridContainer, 0);
            console.log("GridContainer added to box_game.");
        } else {
            console.error("box_game is not assigned in the editor! Grid cannot be drawn.");
            // 备选方案：添加到舞台，但这可能不在预期层级
            // Laya.stage.addChild(this.gridContainer);
        }

        // 2. 初始化地形列表UI
        this.initTerrainList();

        // 3. 初始化地图拖拽、导入/导出按钮事件
        this.initMapDragEvents();

        // 4. 初始化格子（加载JSON数据、设置状态、绘制可视化格子）
        this.initGrids(this.mapId);


        console.log("MainScript onAwake finished.");


    }

    /**
     * 初始化地形列表UI及事件监听
     */
    private initTerrainList(): void {
        if (!this.box_list) {
            console.error("box_list is not assigned in the editor! Cannot initialize TerrainList.");
            return;
        }
        this.terrainList = new TerrainList(); // 假设 TerrainList 构造函数或内部方法会创建UI
        this.box_list.addChild(this.terrainList);
        // 监听从 TerrainList 组件派发的 'terrainSelected' 事件
        this.terrainList.on('terrainSelected', this, this.onTerrainSelected);
        console.log("TerrainList initialized and added to box_list.");
    }

    /**
     * 初始化地图格子：加载数据、设置内部状态、触发绘制
     */
    private initGrids(map_id: string): void {
        // 检查必要的容器是否存在
        if (!this.box_game || !this.gridContainer) {
            console.warn("Cannot initialize grids: Image_map, box_game, or gridContainer is missing or not ready.");
            return;
        }
        console.log("Initializing grids...");
        // 清除旧的格子绘制 (如果需要重新加载)
        this.gridContainer.graphics.clear();
        // 开始加载格子数据文件
        this.loadGridData(map_id);
    }

    /**
     * 加载 map_grid.json 文件，处理数据并触发后续操作
     */
    private loadGridData(map_id: string): void {
        const jsonPath = `configs/map/map_grid${map_id}.json`; // 确保这个路径相对于 index.html 是正确的
        console.log(`Loading grid data from: ${jsonPath}`);
        Laya.loader.load(jsonPath, Laya.Handler.create(this, (res: any) => {
            if (res && Array.isArray(res.data)) {
                this.gridData = res.data; // 存储从JSON加载的原始格子数据
                console.log(`Loaded ${this.gridData.length} grid cells from ${jsonPath}.`);

                // 初始化内部逻辑用的 mapGrid 状态数组
                // this.initializeMapGridState(this.gridData);
                this.mapGrid = this.gridData;
                // 绘制可视化格子
                // this.drawGrid(this.gridData);

            } else {
                console.error(`Failed to load or parse ${jsonPath}. Ensure the file exists, is valid JSON, and accessible.`);
                this.gridData = [];
                this.mapGrid = [];
                this.showTip(`错误: 无法加载地图格子数据 (${jsonPath})!`);
            }
        }), null, Laya.Loader.JSON); // 明确指定加载类型为 JSON
    }

    /**
     * 根据加载的格子数据初始化 mapGrid 状态数组 (用于放置逻辑)
     * @param loadedGridData 从 JSON 加载的格子数据数组
     */



    /**
     *  绘制可视化格子
     *  根据存储的 gridData 绘制所有格子到 gridContainer
     * @param gridDataToDraw 格子数据数组
     */
    private drawGrid(gridDataToDraw: Array<Array<{ id: number, x: number, y: number, row: number, column: number, type: number }>>): void {
        if (!this.gridContainer) {
            console.error("Grid container not initialized, cannot draw grid.");
            return;
        }
        this.gridContainer.graphics.clear();

        if (!gridDataToDraw || gridDataToDraw.length === 0) {
            console.warn("No grid data provided to draw.");
            return;
        }

        const halfWidth = this.gridWidth / 2;
        const halfVisualHeight = this.gridVisualHeight / 2;

        // 定义菱形的顶点，相对于中心点 (0,0)
        // 在等角投影中，菱形的四个顶点
        const diamondPoints = [
            0, -halfVisualHeight,    // 上顶点
            halfWidth, 0,            // 右顶点
            0, halfVisualHeight,     // 下顶点
            -halfWidth, 0            // 左顶点
        ];

        // 遍历二维数组
        for (let row = 0; row < gridDataToDraw.length; row++) {
            for (let col = 0; col < gridDataToDraw[row].length; col++) {
                const tile = gridDataToDraw[row][col];

                // 计算等角坐标
                // 偶数行向右偏移半个格子宽度
                const offsetX = (row % 2) * halfWidth;
                const centerX = col * this.gridWidth + offsetX + halfWidth;
                const centerY = row * this.gridRowSpacing + halfVisualHeight;

                let lineColor = "#cccccc";
                let lineWidth = 1;

                // 根据格子类型设置样式
                if (tile.type === -1) {
                    lineColor = "#ff0000";
                } else if (tile.type === 0) {
                    lineColor = "#dddddd";
                }

                // 绘制菱形
                this.gridContainer.graphics.drawPoly(
                    centerX,
                    centerY,
                    diamondPoints,
                    null, // 填充色
                    lineColor,
                    lineWidth
                );
            }
        }
    }

    /**
     * 将格子坐标 (row, col) 转换为对应格子中心的屏幕坐标 (x, y)
     * 这个计算逻辑必须与生成 JSON 时 Python 脚本的逻辑相对应，并返回中心点。
     * @param row 格子行号
     * @param col 格子列号
     * @returns 屏幕坐标对象 { x, y }，代表格子中心
     */
    private gridToScreen(row: number, col: number): { x: number, y: number } {
        const tileX_topleft = (row % 2) * (this.gridWidth / 2) + col * this.gridWidth;
        // Y 坐标基于行间距 (12.5)
        const tileY_topleft = row * this.gridRowSpacing;

        // 中心点 Y = 左上角 Y + 菱形视觉高度的一半 (12.5)
        const centerX = tileX_topleft //+ this.gridWidth / 2;
        const centerY = tileY_topleft //+ this.gridVisualHeight / 2; // 使用 12.5

        return { x: centerX, y: centerY };
    }


    /**
     * 将世界坐标转换为等角地图格子坐标
     * @param x 世界坐标X
     * @param y 世界坐标Y
     * @returns 格子坐标 {row, col}
     */
    public sceneToGrid(x: number, y: number): { row: number, col: number } {
        const adjustedY = y

        // 计算行号 (row)
        const row = Math.floor(adjustedY / this.gridRowSpacing);
        let col = -1
        if (row % 2 == 0) {
            col = Math.floor(x / (this.gridWidth));

        } else {
            col = Math.floor((x - this.gridWidth / 2) / (this.gridWidth));
        }
        // 计算列号 (col)

        return { row, col };
    }
    /**
     * 将屏幕坐标 (x, y) 转换为最近的格子坐标 (row, col)
     * 这是 gridToScreen 的逆运算，使用查找最近中心点的方法。
     * @param x 屏幕X坐标
     * @param y 屏幕Y坐标
     * @returns 最近的有效格子坐标对象 { row, col }
     */
    private screenToGridInOther(x: number, y: number): { row: number, col: number } {
        const tileW = this.gridWidth;
        const tileH = this.gridRowSpacing; // 使用行间距 12.5 进行计算
        const tileVisualH_half = this.gridVisualHeight / 2; // 菱形半高 12.5

        // 估算 row: centerY = row * tileH + tileVisualH_half => row = (y - tileVisualH_half) / tileH
        const approxRow = Math.round((y - tileVisualH_half) / tileH);
        // 估算 col: centerX = (row % 2)*(tileW/2) + col*tileW + tileW/2 => col = (x - (row%2)*(tileW/2) - tileW/2) / tileW
        const rowOffsetX = (approxRow % 2) * (tileW / 2);
        const approxCol = Math.round((x - rowOffsetX - tileW / 2) / tileW);

        // --- 精确查找最近的格子中心 ---
        let closestRow = -1;
        let closestCol = -1;
        let minDistanceSq = Infinity;

        // 搜索中心点 (approxRow, approxCol) 及其周围 3x3 的格子
        for (let rOffset = -1; rOffset <= 1; rOffset++) {
            for (let cOffset = -1; cOffset <= 1; cOffset++) {
                const testRow = approxRow + rOffset;
                const testCol = approxCol + cOffset;

                // 检查计算出的 row/col 是否在 mapGrid 的有效范围内
                if (testRow < 0 || testCol < 0 ||
                    testRow >= this.mapGrid.length ||
                    !this.mapGrid[testRow] || // 确保行存在
                    testCol >= this.mapGrid[testRow].length) {
                    continue; // 超出已知地图范围或无效索引
                }

                // 计算测试格子的中心点屏幕坐标
                const testCenter = this.gridToScreen(testRow, testCol);

                // 计算屏幕点 (x, y) 到测试格子中心的距离平方
                const dx = x - testCenter.x;
                const dy = y - testCenter.y;
                const distanceSq = dx * dx + dy * dy;

                // 如果距离更近，更新最近的格子
                if (distanceSq < minDistanceSq) {
                    minDistanceSq = distanceSq;
                    closestRow = testRow;
                    closestCol = testCol;
                }
            }
        }

        // 如果经过搜索仍然没有找到有效的格子 (例如地图数据为空或点击在非常远的地方)
        if (closestRow === -1 || closestCol === -1) {
            console.warn(`Could not find valid grid cell near screen coordinates (${x.toFixed(1)}, ${y.toFixed(1)}). Returning approximate or default.`);
            // 返回一个基于粗略估计的安全值，例如限制在 (0, 0)
            const safeRow = Math.max(0, approxRow);
            const safeCol = Math.max(0, approxCol);
            // 进一步检查这个安全值是否真的在范围内
            if (safeRow < this.mapGrid.length && this.mapGrid[safeRow] && safeCol < this.mapGrid[safeRow].length) {
                return { row: safeRow, col: safeCol };
            } else {
                return { row: 0, col: 0 }; // Fallback to origin if even approx is bad
            }
        }

        // 返回找到的最近的有效格子的坐标
        return { row: closestRow, col: closestCol };
    }

    // ============================================================
    //  地形处理、拖拽、放置、导入/导出等逻辑
    // ============================================================

    /**
     * 初始化键盘事件监听
     */
    // private initKeyboardEvents(): void {
    //     Laya.stage.on(Laya.Event.KEY_DOWN, this, this.onKeyDown);
    // }

    /**
     * 处理键盘按下事件
     * @param e 键盘事件对象
     */
    onKeyDown(e: Laya.Event): void {
        // 如果没有选中的地形，直接返回
        if (!this.selectedTerrain) return;
        let terrain = this.selectedTerrain

        let offsetX1 = this.selectedTerrain.width / 2 - this.selectedTerrain.width & this.selectedTerrain.anchorX + 25


        let currentPos = this.sceneToGrid(this.selectedTerrain.x - offsetX1, this.selectedTerrain.y - 25);
        console.log("currentPos", currentPos);
        let newRow = currentPos.row;
        let newCol = currentPos.col;
        console.log(e.keyCode)
        // 根据按键移动地形
        switch (e.keyCode) {
            case 87: // W键 - 上
            case 38: // 上箭头
                newRow--;
                break;
            case 83: // S键 - 下
            case 40: // 下箭头
                newRow++;
                break;
            case 65: // A键 - 左
            case 37: // 左箭头
                newCol--;
                break;
            case 68: // D键 - 右
            case 39: // 右箭头
                newCol++;
                break;
            case 8:
                if (terrain.parent) { // 确保它还在场景中
                    // 清除地图格子状态
                    this.clearOccupiedGridsInState(terrain); // 确保清除的是最新的占用格子

                    // 从父节点移除并销毁
                    terrain.removeSelf();
                    terrain.destroy(true); // true 表示销毁子节点（如果地形有的话）
                    this.showTip("地形已删除");

                    // 如果双击的是当前选中的地形，取消选中状态
                    if (this.selectedTerrain === terrain) {
                        this.selectedTerrain = null;
                    }
                    // 如果恰好正在拖动这个地形（虽然不太可能，双击通常快于拖动结束），也取消拖动
                    if (this.draggingTerrain === terrain) {
                        this.draggingTerrain = null;
                    }
                }
                break
            default:
                return; // 其他按键不处理
        }

        // 保存原始位置，以便移动失败时恢复
        const originalX = this.selectedTerrain.x;
        const originalY = this.selectedTerrain.y;
        console.log("newRow", newRow);
        console.log("newCol", newCol);
        // 计算新的屏幕坐标
        const newScreenPos = this.gridToScreen(newRow, newCol);

        // 清除当前占用的格子
        this.clearOccupiedGridsInState(this.selectedTerrain);

        // 移动地形到新位置
        let offsetX = this.selectedTerrain.width / 2 - this.selectedTerrain.width * this.selectedTerrain.anchorX + 25;
        this.selectedTerrain.pos(newScreenPos.x, newScreenPos.y);
        console.log(newScreenPos.x, newScreenPos.y);
        // 检查新位置是否有效
        const isValid = this.checkAndUpdateTerrainGrids(this.selectedTerrain, newScreenPos.x, newScreenPos.y);

        if (isValid) {
            // 更新地形的网格位置
            this.selectedTerrain.posGrid = { row: newRow, col: newCol };
            // 更新z轴排序
            // this.selectedTerrain.zOrder = newRow * 1000 + newCol;


            this.drawOccupiedGrids(this.selectedTerrain)
            // 标记新位置的占用状态
            this.markOccupiedGridsInState(this.selectedTerrain);
        } else {
            // 如果新位置无效，恢复到原始位置
            this.selectedTerrain.pos(originalX, originalY);
            // 重新标记原始位置的占用状态
            this.checkAndUpdateTerrainGrids(this.selectedTerrain, originalX, originalY);
            this.markOccupiedGridsInState(this.selectedTerrain);
        }
    }

    /**
     * 当从地形列表选择一个地形时的处理函数
     * @param type 地形类型 (从 TerrainList 传递)
     * @param id 地形配置ID (从 TerrainList 传递)
     * @param icon 地形图标路径 (从 TerrainList 传递)
     */
    private onTerrainSelected(type: number, id: number, icon: string): void {
        console.log(`Terrain selected from list: type=${type}, id=${id}, icon=${icon}`);
        let terrainConfig = TerrainConfigManager.getInstance().getTerrainConfig(id)
        const terrain = this.createTerrain(terrainConfig);
        if (this.box_map) { // 确保地形容器存在
            this.addTerrainToMap(terrain);
        } else {
            console.error("box_map is not assigned! Cannot add selected terrain to map.");
            // 可能需要销毁创建的 terrain 对象以防内存泄漏
            terrain?.destroy(true);
        }
    }

    /**
     * 创建地形对象的实例并进行初始化设置
     * @param type 地形类型
     * @param id 地形ID
     * @param icon 地形图标资源路径
     * @returns 创建好的 Terrain 实例，或 null 如果失败
     */
    private createTerrain(terrainConfig: TerrainConfigItem): Terrain | null {
        try {
            const terrain = new Terrain(); // 实例化 Terrain 类
            // 调用初始化方法，传递必要的数据
            terrain.initTerrain(terrainConfig);

            // **重要**: 设置地形对象的锚点。等角对象通常建议锚点设在底部中心或中心。
            // 这会影响 pos(x, y) 的行为以及后续坐标计算。
            // 假设 Terrain 类内部处理了锚点，或者我们在这里统一设置：
            // terrain.anchorX = 0.5; // 中心锚点
            // terrain.anchorY = 0.5; // 中心锚点
            // 如果锚点是底部中心：
            // terrain.anchorY = 1.0;

            return terrain;
        } catch (error) {
            console.error(`Failed to create Terrain instance (id: ${terrainConfig.id}, icon: ${terrainConfig.icon}):`, error);
            this.showTip("创建地形对象失败！");
            return null;
        }
    }

    /**
     * 将新创建或加载的地形添加到地图上，设置初始位置，并处理放置逻辑
     * @param terrain 要添加到地图的 Terrain 实例
     */
    private addTerrainToMap(terrain: Terrain): void {
        if (!this.box_map || !terrain) {
            console.error("Cannot add terrain: box_map or terrain instance is null.");
            return;
        }
        this.box_map.addChild(terrain); // 添加到地形层 (box_map)

        // 设定一个初始屏幕位置，例如地图中心或鼠标点击位置附近
        // 注意：pos(x, y) 设置的是锚点的位置
        const initialScreenX = terrain.width * 2
        const initialScreenY = terrain.height * 2

        // 将初始位置对齐到最近的格子中心
        const initialGridPos = this.sceneToGrid(initialScreenX, initialScreenY);

        terrain.pos(initialScreenX, initialScreenY); // 移动到找到的有效位置
        terrain.zOrder=100000
        // 为成功放置的地形添加拖拽事件
        this.addTerrainDragEvents(terrain);
    }

    /**
     * 检查并更新地形占用的格子信息，并返回是否有效
     * @param terrain
     * @returns boolean 地形当前位置是否有效
     */
    private checkAndUpdateTerrainGrids(terrain: Terrain, posx: number, posy: number): boolean {
        if (!terrain || !terrain.updateOccupiedGrids) {
            console.error("Terrain object is invalid or missing 'updateOccupiedGrids' method.");
            return false;
        }
        // 调用 Terrain 实例的方法来计算和检查
        return terrain.updateOccupiedGrids(
            this.gridWidth,
            this.gridVisualHeight,
            posx, // 当前中心 x
            posy, // 当前中心 y
            this.mapGrid, // 传递地图状态数组
            this.sceneToGrid.bind(this), // Pass the screenToGrid function bound to 'this'
            this.gridToScreen.bind(this)
        );
    }


    /**
     * 在 mapGrid 状态数组中标记地形占用的格子
     * @param terrain 地形对象，应包含其已计算好的 occupiedGrids 列表
     */
    private markOccupiedGridsInState(terrain: Terrain): void {
        if (!terrain || !terrain.occupiedGrids || terrain.occupiedGrids.length === 0) {
            // console.warn("Terrain has no occupiedGrids to mark state for.");
            return; // 没有要标记的格子
        }
        const terrainIdToMark = terrain.type !== 0 ? terrain.type : -2; // 使用地形 type 或通用占用标记 (-2)
        // console.log(`Marking ${terrain.occupiedGrids.length} grids in state for terrain id ${terrain.id} with value ${terrainIdToMark}`);

        // 记录最大的行列坐标
        let maxRow = -1;
        let maxCol = -1;

        for (const grid of terrain.occupiedGrids) {
            // 更新最大坐标
            // maxRow = Math.max(maxRow, grid.row);
            if (maxRow < grid.row) {
                maxRow = grid.row
                maxCol = grid.col
            }
            // 再次检查边界，确保安全
            if (grid.row >= 0 && grid.row < this.mapGrid.length &&
                this.mapGrid[grid.row] && // 确保行存在
                grid.col >= 0 && grid.col < this.mapGrid[grid.row].length) {
                // 仅当格子当前为空(0)时标记，防止覆盖其他地形？或者允许覆盖？
                // 当前逻辑：直接覆盖，放置时 isTerrainPositionValid 会检查
                this.mapGrid[grid.row][grid.col].type = terrainIdToMark;
            } else {
                console.warn(`Attempted to mark out-of-bounds grid state: ${grid.row}, ${grid.col} for terrain ${terrain.id}`);
            }
        }

        // 设置地形的最大格子坐标
        if (maxRow !== -1 && maxCol !== -1) {
            // terrain.maxGridPosition = { row: maxRow, col: maxCol };
            console.log("nax: ", maxRow, maxCol,)
            let pos = this.gridToScreen(maxRow, maxCol);
            // 根据新的锚点计算方式调整位置
            let offsetX = terrain.width / 2 - terrain.width & terrain.anchorX + 25
            terrain.pos(pos.x + offsetX, pos.y + 25);
            terrain.posGrid = { row: maxRow, col: maxCol };
            if (terrain.type === TerrainType.GRASS || terrain.type === TerrainType.ROAD || terrain.type === TerrainType.BRIDGE || terrain.type === TerrainType.PORTAL) {
                // 地面类型使用较小的倍数
                terrain.zOrder = maxCol * 5 + maxRow * 2;
            } else {
                // 建筑、树木等物体使用较大的倍数，但不要差距过大
                // terrain.zOrder = maxCol * 100 + maxRow * 200 + 100;
                terrain.zOrder = (terrain.y - 25 - terrain.baseGridHeight / 2 * 12.5) * 10 //terrainConfig.col * 100 + terrainConfig.row * 200 + 100;

            }
        }
        // terrain.zOrder = terrain.posGrid.row * 1000 + terrain.posGrid.col;

    }

    /**
     * 在 mapGrid 状态数组中清除地形占用的格子，将其恢复为可通过状态 (0)
     * @param terrain 地形对象，需要其 occupiedGrids 列表
     */
    private clearOccupiedGridsInState(terrain: Terrain): void {
        if (!terrain || !terrain.occupiedGrids || terrain.occupiedGrids.length === 0) {
            // 可能在拖动开始时还没有计算好格子，或者地形本身没有占用格子
            // console.warn("Terrain has no occupiedGrids to clear state for.");
            return;
        }
        const terrainMarkValue = terrain.type !== 0 ? terrain.type : -2;
        // console.log(`Clearing grid state for terrain id ${terrain.id} (value ${terrainMarkValue})`);

        for (const grid of terrain.occupiedGrids) {
            // 边界检查
            if (grid.row >= 0 && grid.row < this.mapGrid.length &&
                this.mapGrid[grid.row] &&
                grid.col >= 0 && grid.col < this.mapGrid[grid.row].length) {
                // **重要**: 只清除由当前这个地形实例标记的格子
                // 避免错误地清除其他地形占用的格子
                if (this.mapGrid[grid.row][grid.col].type === terrainMarkValue) {
                    this.box_game.getChildByName(`grid_mark_${grid.col}_${grid.row}`)?.destroy(true);
                    this.mapGrid[grid.row][grid.col].type = 0; // 恢复为可通过状态 (0)
                } else {
                    // 可能格子已经是 0，或者被其他东西占用了，不用处理
                }
            } else {
                console.warn(`Attempted to clear out-of-bounds grid state: ${grid.row}, ${grid.col} for terrain ${terrain.id}`);
            }
        }
        // 清除后，地形实例内部的 occupiedGrids 列表也应该清空或置为无效，直到下次计算
        // terrain.occupiedGrids = [];
    }

    /**
     * 初始化地图容器的事件监听（用于取消选中）和按钮事件
     */
    private initMapDragEvents(): void {
        // 导出按钮事件
        if (this.box_export) {
            this.box_export.on(Laya.Event.CLICK, this, this.exportMapConfig);
        } else { console.warn("Export button not assigned."); }

        // 加载/导入按钮事件
        if (this.box_load) {
            this.box_load.on(Laya.Event.CLICK, this, this.importMapConfig);
        } else { console.warn("Load button not assigned."); }

        if (this.box_open) {
            this.box_open.on(Laya.Event.CLICK, this, this.opneNPC);
        } else { console.warn("Load button not assigned."); }

        // 地图容器本身的事件 (用于取消选中等)
        if (this.box_map) {
            // MOUSE_DOWN 用于检测点击地图背景
            this.box_map.on(Laya.Event.MOUSE_DOWN, this, this.onMapMouseDown);
        } else {
            console.error("box_map is null, cannot add map mouse down listener for deselection.");
        }

        // 舞台事件监听拖动和释放 (更可靠，因为鼠标可能移出地形或地图容器)
        Laya.stage.on(Laya.Event.MOUSE_MOVE, this, this.onStageMouseMove);
        Laya.stage.on(Laya.Event.MOUSE_UP, this, this.onStageMouseUp);
        // 当鼠标移出整个舞台区域时，也应该视为拖动结束
        Laya.stage.on(Laya.Event.MOUSE_OUT, this, this.onStageMouseUp);
        console.log("Map drag events initialized.");
    }

    /**
     * 为单个地形实例添加拖拽相关的事件监听器
     * @param terrain 要添加事件的地形对象
     */
    private addTerrainDragEvents(terrain: Terrain): void {
        if (!terrain) return;

        // --- 鼠标按下事件 (开始拖动) ---
        terrain.on(Laya.Event.MOUSE_DOWN, this, (e: Laya.Event) => {
            e.stopPropagation(); // 阻止事件冒泡到地图容器 (box_map)，避免触发取消选中
            this.draggingTerrain = terrain;
            this.selectedTerrain = terrain; // 同时设为选中状态

            // 计算鼠标按下位置相对于地形中心点(锚点)的偏移
            // this.offsetX = e.stageX - terrain.x;
            // this.offsetY = e.stageY - terrain.y;

            // 将当前拖动的地形提到渲染顶层，使其在其他地形之上
            if (this.box_map) {
                this.box_map.setChildIndex(terrain, this.box_map.numChildren - 1);
            }

            // **重要**: 在开始拖动时，清除该地形在 mapGrid 中的占用状态
            // 这样拖动过程中检查位置时，不会将自身视为障碍
            this.clearOccupiedGridsInState(terrain);

            // 可选: 添加视觉反馈，比如轻微放大或改变透明度，表示正在拖动
            // terrain.scale(1.05, 1.05);
            // terrain.alpha = 0.8;
            console.log(`Started dragging terrain id: ${terrain.id}`);
        });

        // --- 鼠标抬起事件 (在地形自身上释放) ---
        // 如果在地形上抬起，也应该触发放置逻辑
        terrain.on(Laya.Event.MOUSE_UP, this, (e: Laya.Event) => {
            e.stopPropagation(); // 阻止冒泡到 stage 的 mouse up，避免重复处理
            this.handleTerrainDrop(e, e.stageX, e.stageY); // 使用通用的放置处理函数
        });

        // --- 双击事件 (删除地形) ---
        terrain.on(Laya.Event.DOUBLE_CLICK, this, (e: Laya.Event) => {
            e.stopPropagation(); // 阻止冒泡
            console.log(`Double clicked terrain id: ${terrain.id}`);
            if (terrain.parent) { // 确保它还在场景中
                // 清除地图格子状态
                this.clearOccupiedGridsInState(terrain); // 确保清除的是最新的占用格子

                // 从父节点移除并销毁
                terrain.removeSelf();
                terrain.destroy(true); // true 表示销毁子节点（如果地形有的话）
                this.showTip("地形已删除");

                // 如果双击的是当前选中的地形，取消选中状态
                if (this.selectedTerrain === terrain) {
                    this.selectedTerrain = null;
                }
                // 如果恰好正在拖动这个地形（虽然不太可能，双击通常快于拖动结束），也取消拖动
                if (this.draggingTerrain === terrain) {
                    this.draggingTerrain = null;
                }
            }
        });
    }

    private woundedScript: WoundedScript
    isLoading = false
    async opneNPC() {
        if (this.isLoading) return
        if (this.woundedScript) {
            this.woundedScript.owner.destroy(true);
            this.woundedScript = null;
            this.box_list.visible = true
            this.box_load.visible = true
            this.box_export.visible = true
            this.box_map.mouseEnabled=true
            this.box_game.mouseEnabled=true
            this.box_open.label="打开npc"
            

        } else {
            this.box_open.label="关闭npc"
            this.isLoading = true
            this.box_map.mouseEnabled=false
            let scene = await Laya.Scene.open(`Scene${this.mapId}_1.ls`, false);

            this.woundedScript = scene.getComponent(WoundedScript);
            this.isLoading = false
            this.box_game.mouseEnabled=false
            this.woundedScript.initScript(this.mapGrid, this.mapId)
            this.box_list.visible = false
            this.box_load.visible = false
            this.box_export.visible = false
        }

    }


    /**
     * 处理在地图背景容器 (box_map) 上按下鼠标的事件，通常用于取消选中
     * @param e 事件对象
     */
    private onMapMouseDown(e: Laya.Event): void {
        // 检查事件的目标是否确实是地图容器本身，而不是其子元素（如某个地形）
        if (e.target === this.box_map) {
            if (this.selectedTerrain) {
                console.log("Clicked on map background, deselected terrain.");
                // 可选：移除选中时的视觉效果（如边框）
                // if (this.selectedTerrain.graphics) this.selectedTerrain.graphics.clear();
            }
            this.selectedTerrain = null; // 取消选中
        }
        // 注意：这里不阻止冒泡，以便舞台能接收到事件（如果需要的话）
    }

    /**
     * 处理在舞台 (Stage) 上移动鼠标的事件，用于更新拖动中地形的位置
     * @param e 事件对象
     */
    private onStageMouseMove(e: Laya.Event): void {
        if (this.draggingTerrain) { // 检查是否真的在拖动一个地形
            // 计算地形的新中心点位置 (跟随鼠标，考虑初始偏移)
            const newX = e.stageX - this.offsetX;
            const newY = e.stageY - this.offsetY;

            // 直接更新地形的屏幕位置，让其视觉上跟随鼠标
            this.draggingTerrain.pos(newX, newY);

            // **可选**: 实时显示放置指示器 (会影响性能)
            // this.showPlacementIndicator(this.draggingTerrain);
        }
    }




    /**
     * 处理在舞台 (Stage) 上释放鼠标的事件，用于结束拖动并放置地形
     * @param e 事件对象
     */
    private onStageMouseUp(e: Laya.Event): void {
        // 检查是否是从拖动状态释放
        this.handleTerrainDrop(e, e.stageX, e.stageY); // 使用通用的放置处理函数
    }

    /**
     * 通用的处理地形放下/拖动结束的逻辑
     * @param finalStageX 鼠标最终的舞台 X 坐标
     * @param finalStageY 鼠标最终的舞台 Y 坐标
     */
    private handleTerrainDrop(evt: Laya.Event, finalStageX: number, finalStageY: number): void {
        if (this.draggingTerrain) {
            const terrain = this.draggingTerrain; // 本地引用，方便使用
            console.log(`Dropping terrain id: ${terrain.id}`);

            // 恢复拖动时的视觉效果 (如果修改过)
            // terrain.scale(1.0, 1.0);
            terrain.alpha = 1.0; // 恢复不透明
            // terrain.graphics.clear(); // 清除临时的指示器边框等
            let finalX = evt.stageX - 50//this.buildShowView.x //+ this.buildShowView.width / 2
            let finalY = evt.stageY
            // 1. 计算最终的理论中心位置 (鼠标位置 - 初始偏移)
            // const finalX = finalStageX - this.offsetX;
            // const finalY = finalStageY - this.offsetY;
            console.log(finalX, finalY)
            terrain.pos(finalX, finalY);
            // return 

            // 2. 将理论位置对齐到最近的格子中心
            const targetGrid = this.sceneToGrid(finalX, finalY); // 找到目标格子
            const alignedPos = this.gridToScreen(targetGrid.row, targetGrid.col); // 获取该格子中心点

            // 3. 将地形的锚点移动到对齐后的格子中心位置
            // terrain.pos(alignedPos.x, alignedPos.y);

            // 4. 检查对齐后的位置是否真的有效 (调用 checkAndUpdateTerrainGrids)
            const finalGridsValid = this.checkAndUpdateTerrainGrids(terrain, finalX, finalY);

            if (finalGridsValid) {
                // 5a. 位置有效: 最终确定位置，并在 mapGrid 中标记占用
                console.log(`Terrain id ${terrain.id} placed successfully at grid (${targetGrid.row}, ${targetGrid.col}).`);
                this.markOccupiedGridsInState(terrain); // 更新地图状态


                // 添加视觉标记
                this.drawOccupiedGrids(terrain);

            } else {
                // 5b. 位置无效: 尝试寻找附近最近的有效位置
                console.log(`Final aligned position (${targetGrid.row}, ${targetGrid.col}) is invalid. Attempting to find nearest valid spot...`);
                const validPos = this.findNearestValidPosition(terrain, terrain.x, terrain.y);

                // 检查找到的位置是否和当前无效位置不同 (避免死循环)
                terrain.pos(validPos.x, validPos.y); // 移动到建议位置
                const foundPosValid = this.checkAndUpdateTerrainGrids(terrain, validPos.x, validPos.y); // 再次检查

                if (foundPosValid && (validPos.x !== alignedPos.x || validPos.y !== alignedPos.y)) {
                    // 找到了一个不同的、有效的邻近位置
                    const foundGrid = this.screenToGridInOther(validPos.x, validPos.y);
                    this.showTip("位置冲突，已自动调整到最近可用位置");
                    console.log(`Terrain id ${terrain.id} moved to nearest valid grid (${foundGrid.row}, ${foundGrid.col}).`);
                    this.markOccupiedGridsInState(terrain); // 在新位置标记占用
                    // 在新位置添加视觉标记
                    this.drawOccupiedGrids(terrain);
                } else {
                    // 5c. 如果找不到有效位置，或者找到的位置还是无效/与原位相同，则放置失败
                    this.showTip("附近无可用位置，无法放置该地形");
                    console.log(`Failed to place terrain id ${terrain.id}, no valid position found near (${targetGrid.row}, ${targetGrid.col}). Removing.`);
                    terrain.removeSelf(); // 从场景移除
                    terrain.destroy(true); // 销毁对象
                    // 如果放置失败的是当前选中的，取消选中
                    if (this.selectedTerrain === terrain) this.selectedTerrain = null;
                }
            }

            // 6. 无论成功与否，结束拖动状态
            this.draggingTerrain = null;
            console.log("Dragging finished.");
            // 注意：selectedTerrain 保持选中状态，除非放置失败或点击背景取消
        }
    }


    /**
    * 为地形占用的格子绘制视觉标记
    * @param terrain 要标记的地形对象
    */
    private drawOccupiedGrids(terrain: Terrain): void {
        // return
        if (!terrain || !terrain.occupiedGrids || terrain.occupiedGrids.length === 0) return;
        // 为每个占用的格子创建视觉标记
        let lineColor = "#000000"; // 默认格子线颜色 (浅灰色)
        //随机颜色
        // lineColor = "#" + Math.floor(Math.random()*16777215).toString(16);
        if (terrain.type === TerrainType.ROAD) {
            lineColor = "#000000"; // 默认格子线颜色 (浅灰色)
        }
        // 根据地形类型设置不同的颜色
        for (const grid of terrain.occupiedGrids) {
            const screenPos = this.gridToScreen(grid.row, grid.col);

            // 创建一个矩形标记
            const mark = new Laya.Sprite();
            mark.name = "grid_mark_" + grid.col + "_" + grid.row; // 用于后续清除

            mark.pos(screenPos.x, screenPos.y);
            // mark.alpha = 0.3; // 半透明

            const halfWidth = this.gridWidth / 2;
            const halfVisualHeight = this.gridVisualHeight / 2; // = 12.5

            // 定义菱形的顶点，相对于中心点 (0,0)
            // Y轴向下为正
            const diamondPoints = [
                0, -halfVisualHeight,    // Top vertex (中心点 Y - 半高)
                halfWidth, 0,              // Right vertex (中心点 X + 半宽)
                0, halfVisualHeight,     // Bottom vertex (中心点 Y + 半高)
                -halfWidth, 0               // Left vertex (中心点 X - 半宽)
            ];

            // **重要**: 使用 JSON 中的 x, y。这些是根据 Python 脚本逻辑计算好的单元格“逻辑原点”（在你的例子中是左上角）
            // 菱形的视觉中心点应该是 (逻辑原点x + 半宽, 逻辑原点y + 半高)
            const centerX = halfWidth;
            const centerY = halfVisualHeight; // 注意这里用的是 gridHeight (行间距)，正好是菱形高度的一半

            let lineWidth = 1;


            mark.graphics.drawPoly(centerX, centerY, diamondPoints, lineColor, lineColor, lineWidth);



            this.box_game.addChild(mark);
        }
    }



    /**
     * 检查地形在当前位置是否有效（所有占用的格子都必须是可通过的）
     * 实际的检查逻辑封装在 checkAndUpdateTerrainGrids 中
     * @param terrain 要检查的地形对象
     * @returns boolean 位置是否有效
     */
    private isTerrainPositionValid(terrain: Terrain): boolean {
        // 简单地调用封装好的检查方法
        return this.checkAndUpdateTerrainGrids(terrain, terrain.x, terrain.y);
    }


    /**
     * 当地形放置位置无效时，尝试在其周围寻找最近的一个有效格子中心点位置
     * @param terrain 要寻找位置的地形对象
     * @param startX 无效位置的 X 坐标 (中心点)
     * @param startY 无效位置的 Y 坐标 (中心点)
     * @returns 最近的有效位置 { x, y } (中心点坐标)，如果找不到则返回原始的 startX, startY
     */
    private findNearestValidPosition(terrain: Terrain, startX: number, startY: number): { x: number, y: number } {
        // 保存原始位置和格子状态，因为检查过程会临时修改它们
        const originalX = terrain.x;
        const originalY = terrain.y;
        const originalGrids = terrain.occupiedGrids ? [...terrain.occupiedGrids] : [];

        // 检查起始位置本身（虽然调用此函数时通常已知无效，但作为基础情况）
        terrain.pos(startX, startY);
        if (this.isTerrainPositionValid(terrain)) {
            terrain.pos(originalX, originalY); // 恢复
            terrain.occupiedGrids = originalGrids;
            return { x: startX, y: startY }; // 起始位置有效，直接返回
        }

        let minDistanceSq = Number.MAX_VALUE;
        let bestPosition = { x: startX, y: startY }; // 默认返回起始位置（如果找不到）
        let foundValid = false;

        const maxSearchRadius = 15; // 限制搜索半径（格子数），防止性能问题和搜索太远
        const startGrid = this.screenToGridInOther(startX, startY); // 起始格子

        // 从半径 1 开始，以菱形/曼哈顿距离方式向外扩展搜索
        for (let radius = 1; radius <= maxSearchRadius; radius++) {
            // 遍历当前半径圈上的所有格子
            for (let dr = -radius; dr <= radius; dr++) {
                const remainingDist = radius - Math.abs(dr);
                for (let dcSign = -1; dcSign <= 1; dcSign += 2) { // 处理正负列偏移
                    const dc = remainingDist * dcSign;
                    // 跳过半径为0的情况（dr=0, dc=0）以及重复计算（当 remainingDist=0 时 dc 会计算两次0）
                    if (dr === 0 && dc === 0) continue;
                    if (remainingDist === 0 && dcSign === 1) continue; // dc=0 已经被 dcSign=-1 处理过了

                    const testRow = startGrid.row + dr;
                    const testCol = startGrid.col + dc;

                    // 快速跳过无效格子坐标
                    if (testRow < 0 || testCol < 0 ||
                        testRow >= this.mapGrid.length ||
                        !this.mapGrid[testRow] ||
                        testCol >= this.mapGrid[testRow].length) {
                        continue;
                    }

                    // 计算测试格子的中心屏幕坐标
                    const testPos = this.gridToScreen(testRow, testCol);

                    // 临时移动地形到测试位置并检查有效性
                    terrain.pos(testPos.x, testPos.y);
                    const isValid = this.isTerrainPositionValid(terrain); // isTerrainPositionValid 内部会调用 checkAndUpdateTerrainGrids

                    if (isValid) {
                        foundValid = true;
                        // 计算从原始无效点 (startX, startY) 到当前有效点 (testPos.x, testPos.y) 的距离平方
                        const distSq = Math.pow(testPos.x - startX, 2) + Math.pow(testPos.y - startY, 2);
                        if (distSq < minDistanceSq) {
                            minDistanceSq = distSq;
                            bestPosition = { x: testPos.x, y: testPos.y }; // 记录这个更好的有效位置
                        }
                    }
                }
            }
            // 如果在当前半径找到了至少一个有效位置，就可以停止搜索，因为我们要找的是最近的
            if (foundValid) {
                break; // 退出外层 radius 循环
            }
        }

        // 恢复地形到原始位置和状态
        terrain.pos(originalX, originalY);
        terrain.occupiedGrids = originalGrids;

        if (foundValid) {
            console.log(`Found nearest valid position at screen coords (${bestPosition.x.toFixed(1)}, ${bestPosition.y.toFixed(1)})`);
        } else {
            console.log("Could not find any valid position within search radius.");
        }

        return bestPosition; // 返回找到的最佳位置，或者原始位置（如果没找到）
    }


    // --- 导出/导入/工具函数 ---

    /**
     * 导出当前地图配置为 JSON 文件
     */
    private exportMapConfig(): void {
        console.log("Exporting map configuration...");
        // 创建配置对象
        const config = {
            // A. 导出地图格子状态数据 (mapGrid)
            // 这记录了哪些格子是边界 (-1)，哪些是空的 (0)，哪些被占用了 (地形 type 或 -2)
            mapGrid: this.gridData,
            gridSize: { width: this.gridWidth, height: this.gridVisualHeight },
            mapSize: { width: this.map_width_pixels, height: this.map_height_pixels },
            // B. 导出所有放置的地形信息
            terrains: [] as Array<{
                id: number; // 地形配置 ID (来自 TerrainConfigManager 或创建时的 ID)
                row: number; // 地形中心点所在的格子行号
                col: number; // 地形中心点所在的格子列号
                occupiedGrids: Array<{ row: number, col: number }>; // 地形占用的格子坐标列表
                // 注意：不再导出 occupiedGrids，因为这可以在加载时根据中心点和地形尺寸重新计算
            }>
        };

        // 遍历地形容器 (box_map) 中的所有子节点
        if (this.box_map) {
            for (let i = 0; i < this.box_map.numChildren; i++) {
                const child = this.box_map.getChildAt(i);
                if (child instanceof Terrain) { // 确保是 Terrain 实例
                    // 获取地形中心点所在的格子坐标
                    // const centerGrid = this.sceneToGrid(child.x, child.y); // 使用中心点坐标转换 


                    config.terrains.push({
                        id: child.id,       // 地形的配置ID
                        row: child.posGrid.row,// 中心格子行
                        col: child.posGrid.col,// 中心格子列
                        occupiedGrids: child.occupiedGrids
                    });
                }
            }
            console.log(`Exporting ${config.terrains.length} terrains.`);
        } else {
            console.error("box_map is null, cannot export terrains.");
            this.showTip("错误：无法访问地形容器");
            return;
        }

        // 将配置对象转换为格式化的 JSON 字符串
        const configJson = JSON.stringify(config, null, 2); // 使用 2 个空格缩进，美化输出

        // 使用浏览器 API 创建并触发下载
        try {
            const blob = new Blob([configJson], { type: 'application/json;charset=utf-8' });
            const url = URL.createObjectURL(blob);
            const link = document.createElement('a');
            link.href = url;
            // 定义下载的文件名
            const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
            link.download = `map_${this.mapId}.json`;

            // 触发隐藏链接的点击事件来开始下载
            document.body.appendChild(link);
            link.click();

            // 清理：从文档移除链接并释放对象 URL
            document.body.removeChild(link);
            URL.revokeObjectURL(url);

            this.showTip("地图配置已成功导出");
            console.log("Map configuration exported successfully.");

        } catch (error) {
            console.error("导出地图配置失败:", error);
            this.showTip("导出失败，请查看控制台日志");
        }
    }

    /**
     * 导入地图配置文件 (JSON)，加载地图状态和地形
     */
    private async importMapConfig() {
        console.log("Import map configuration requested.");

        const input = document.createElement('input');
        input.type = 'file';
        input.accept = '.json';

        input.onchange = (e: Event) => {
            const target = e.target as HTMLInputElement;
            if (!target.files || !target.files[0]) return;

            const file = target.files[0];
            const reader = new FileReader();

            reader.onload = (e) => {
                try {
                    const config = JSON.parse(e.target?.result as string);

                    // 清除当前地图上的所有地形
                    this.clearAllTerrains();

                    // 从 gridData 重建 mapGrid
                    if (config.mapGrid && Array.isArray(config.mapGrid)) {
                        this.gridData = config.mapGrid;

                        // 初始化 mapGrid 二维数组
                        const maxRow = this.gridData.length;//Math.max(...this.gridData.map(g => g.row)) + 1;
                        const maxCol = this.gridData[0].length// Math.max(...this.gridData.map(g => g.column)) + 1;
                        this.mapGrid = this.gridData//Array(maxRow).fill(0).map(() => Array(maxCol).fill(0));


                    }

                    // 加载所有地形
                    if (config.terrains && Array.isArray(config.terrains)) {
                        for (const terrainConfig of config.terrains) {
                            const terrainData = TerrainConfigManager.getInstance().getTerrainConfig(terrainConfig.id);
                            if (!terrainData) {
                                console.error(`未找到ID为 ${terrainConfig.id} 的地形配置`);
                                continue;
                            }

                            const terrain = this.createTerrain(
                                terrainData

                            );

                            if (this.box_map) {
                                const screenPos = this.gridToScreen(terrainConfig.row, terrainConfig.col);
                                terrain.pos(screenPos.x, screenPos.y);
                                terrain.occupiedGrids = terrainConfig.occupiedGrids;
                                this.markOccupiedGridsInState(terrain)
                                // 添加视觉标记
                                this.drawOccupiedGrids(terrain);
                                if (terrainData.type === TerrainType.GRASS || terrainData.type === TerrainType.ROAD) {
                                    this.addTerrainDragEvents(terrain);

                                } else {
                                    this.addTerrainDragEvents(terrain);

                                }
                                // if (terrainData.type === TerrainType.GRASS || terrainData.type === TerrainType.ROAD || terrainData.type === TerrainType.BRIDGE || terrainData.type === TerrainType.PORTAL) {
                                //     terrain.zOrder = terrainConfig.row * 21.03 + terrainConfig.cow * 10.03;

                                // } else {
                                //     terrain.zOrder = terrainConfig.row * 210.3 + terrainConfig.cow * 10.03;
                                // }
                                this.box_map.addChild(terrain);

                            }
                        }
                    }

                    this.showTip("地图配置加载成功");
                } catch (error) {
                    console.error("加载地图配置失败:", error);
                    this.showTip("地图配置加载失败");
                }
            };

            reader.readAsText(file);
        };

        input.click();
    }

    /**
     * 清除地图容器 (box_map) 中所有 Terrain 类型的子节点
     */
    private clearAllTerrains(): void {
        if (!this.box_map) {
            console.warn("box_map is null, cannot clear terrains.");
            return;
        }
        console.log("Clearing all terrains from map container...");
        let clearedCount = 0;
        // 从后往前遍历并移除，这样更安全，不会因为移除导致索引变化而出错
        for (let i = this.box_map.numChildren - 1; i >= 0; i--) {
            const child = this.box_map.getChildAt(i);
            if (child instanceof Terrain) { // 只移除 Terrain 实例
                child.removeSelf(); // 从父节点移除
                child.destroy(true); // 彻底销毁对象及其子节点
                clearedCount++;
            }
        }
        // **重要**: 清除地形后，需要重置 mapGrid 中被它们占用的格子状态
        this.resetMapGridState();

        console.log(`Cleared ${clearedCount} terrains.`);
        // 重置选中和拖动状态
        this.selectedTerrain = null;
        this.draggingTerrain = null;
    }

    /**
     * 重置 mapGrid 状态数组，将所有非边界 (-1) 的格子恢复为可通过状态 (0)
     */
    private resetMapGridState(): void {
        console.log("Resetting mapGrid state...");
        if (!this.mapGrid || this.mapGrid.length === 0) {
            console.warn("mapGrid is empty, cannot reset state.");
            return;
        }
        let resetCount = 0;
        for (let r = 0; r < this.mapGrid.length; r++) {
            if (!this.mapGrid[r]) continue;
            for (let c = 0; c < this.mapGrid[r].length; c++) {
                // 只重置非边界格子
                if (this.mapGrid[r][c].type !== -1) {
                    if (this.mapGrid[r][c].type !== 0) resetCount++; // 统计被重置的格子数
                    this.mapGrid[r][c].type = 0; // 设为可通过 (0)
                }
            }
        }
        console.log(`mapGrid state reset. ${resetCount} cells set to 0 (passable).`);
    }

    /**
     * 在屏幕上显示一个短暂的提示信息
     * @param message 要显示的消息文本
     */
    private showTip(message: string): void {
        // 移除可能存在的上一个提示，避免重叠
        const oldTip = Laya.stage.getChildByName("globalTip") as Laya.Label;
        if (oldTip) {
            Laya.timer.clear(this, oldTip.removeSelf); // 清除旧提示的移除计时器
            oldTip.removeSelf(); // 立即移除旧提示
        }

        // 创建新的 Label 作为提示
        const tip = new Laya.Label();
        tip.name = "globalTip"; // 给提示命名，方便查找和移除
        tip.text = message;
        tip.fontSize = 24; // 设置合适的字体大小
        tip.color = "#ffffff"; // 白色文字
        tip.bgColor = "#000000cc"; // 半透明黑色背景，增加可读性
        tip.padding = "10,15,10,15"; // 设置内边距，让文字不贴边
        tip.anchorX = 0.5; // 设置锚点为中心，方便定位
        tip.anchorY = 0.5;
        // 定位到舞台顶部中间
        tip.pos(Laya.stage.width / 2, Laya.stage.height * 0.1);
        tip.zOrder = 10000; // 设置一个较高的 Z 轴顺序，确保在最上层显示

        Laya.stage.addChild(tip); // 将提示添加到舞台

        // 设置一个定时器，在 2 秒后自动移除提示
        Laya.timer.once(2000, this, () => {
            if (tip.parent) { // 检查提示是否还存在于舞台上
                tip.removeSelf(); // 从舞台移除
            }
            // LayaAir 会自动进行垃圾回收，通常不需要手动调用 tip.destroy()
        });
    }


    /**
     * 组件销毁时执行，用于清理事件监听器和定时器
     */
    onDestroy(): void {
        console.log("MainScript onDestroy called. Cleaning up listeners and timers.");

        // 移除添加到舞台的事件监听器
        Laya.stage.off(Laya.Event.MOUSE_MOVE, this, this.onStageMouseMove);
        Laya.stage.off(Laya.Event.MOUSE_UP, this, this.onStageMouseUp);
        Laya.stage.off(Laya.Event.MOUSE_OUT, this, this.onStageMouseUp);

        // 移除添加到地图容器的事件监听器
        if (this.box_map) {
            this.box_map.off(Laya.Event.MOUSE_DOWN, this, this.onMapMouseDown);
        }

        // 移除地形列表的事件监听
        if (this.terrainList) {
            this.terrainList.off('terrainSelected', this, this.onTerrainSelected);
            // 如果 TerrainList 是 Laya.Script 或自定义组件，可能也需要调用其 destroy 方法
            // this.terrainList.destroy();
        }

        // 移除按钮的事件监听
        this.box_export?.off(Laya.Event.CLICK, this, this.exportMapConfig);
        this.box_load?.off(Laya.Event.CLICK, this, this.importMapConfig);

        // 清理所有与此对象关联的 Laya.timer 定时器
        Laya.timer.clearAll(this);

        // 其他可能的清理，例如取消网络请求等

        console.log("MainScript cleanup complete.");
    }

} // End of MainScript class